﻿using DeviceCommon;
using LogLib;
using Newtonsoft.Json.Linq;
using System;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace Reader
{
    public class CVR100DReader : DeviceBase
    {
        private bool isReading = false;

        private Polling poll = null;

        /// <summary>
        /// 阅读器选项
        /// </summary>
        protected IDCReaderOption _option = new IDCReaderOption();
        public IDCReaderOption Option
        {
            get { return _option; }
            set { _option = value; }
        }

        /// <summary>
        /// 阅读器连接的串口号（或者USB接口索引）
        /// </summary>
        protected int _iPort = 0;
        public int iPort
        {
            get { return _iPort; }
        }

        private string _appDirectory = "";
        public string AssemblyDirectory
        {
            get
            {
                if (string.IsNullOrEmpty(_appDirectory))
                {
                    string directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);
                    _appDirectory = directory.Substring(6);
                }
                return _appDirectory;
            }
        }

        private string CardZPPath = "";

        private string CardWZFile = "";

        public CVR100DReader()
        {         
            LoadConfig();
        }

        public bool CloseCVRReader()
        {
            int num = TermbDll_100D.CVR_CloseComm();
            Log.WriteAsync(string.Format("关闭身份证阅读器{0}", (num == 1) ? "成功" : "失败"));
            return (num == 1);
        }

        private bool ReadCard(out IdCardInfo sender)
        {
            sender = null;
            if (isReading)
            {
                return false;
            }
            isReading = true;         
            int num = 0;
            try
            {
                num = TermbDll_100D.CVR_Authenticate();
                if (num != 1)
                {
                    _error = string.Format("调用CVR_Authenticate返回值{0}，认证失败", num);
                    Log.WriteAsync(_error);
                    return false;
                }
                Log.WriteAsync("调用CVR_Authenticate，认证成功");
                num = TermbDll_100D.CVR_Read_Content(4);
                if (num != 1)
                {
                    _error = string.Format($"调用CVR_Read_Content返回值{num}，读身份证失败.");
                    Log.WriteAsync(_error);
                    return false;
                }
                Log.WriteAsync("获取身份证详细信息");
                int strLen = 30;
                byte[] bytes = new byte[strLen];
                TermbDll_100D.GetPeopleName(ref bytes[0], ref strLen);
                strLen = 0x24;
                byte[] buffer2 = new byte[strLen];
                TermbDll_100D.GetPeopleIDCode(ref buffer2[0], ref strLen);
                strLen = 30;
                byte[] buffer3 = new byte[strLen];
                TermbDll_100D.GetPeopleNation(ref buffer3[0], ref strLen);
                strLen = 0x10;
                byte[] buffer4 = new byte[strLen];
                TermbDll_100D.GetStartDate(ref buffer4[0], ref strLen);
                strLen = 0x10;
                byte[] buffer5 = new byte[strLen];
                TermbDll_100D.GetPeopleBirthday(ref buffer5[0], ref strLen);
                strLen = 70;
                byte[] buffer6 = new byte[strLen];
                TermbDll_100D.GetPeopleAddress(ref buffer6[0], ref strLen);
                strLen = 0x10;
                byte[] buffer7 = new byte[strLen];
                TermbDll_100D.GetEndDate(ref buffer7[0], ref strLen);
                strLen = 30;
                byte[] buffer8 = new byte[strLen];
                TermbDll_100D.GetDepartment(ref buffer8[0], ref strLen);
                strLen = 30;
                byte[] buffer9 = new byte[strLen];
                TermbDll_100D.GetPeopleSex(ref buffer9[0], ref strLen);
                strLen = 0x400;
                byte[] buffer10 = new byte[strLen];
                TermbDll_100D.GetFPDate(ref buffer10[0], ref strLen);
                StringBuilder builder = new StringBuilder();
                int index = 0;
                while (true)
                {
                    bool flag2 = (index < 0x400);
                    if (flag2)
                    {
                        builder.Append(string.Format("{0:X2}", buffer10[index]));
                        index++;
                        continue;
                    }
                    Encoding unicode = Encoding.Unicode;
                    string str2 = unicode.GetString(buffer2).Replace("\0", "").Trim();
                    string dateTime = unicode.GetString(buffer4).Replace("\0", "").Trim();
                    string time = unicode.GetString(buffer7).Replace("\0", "").Trim();
                    flag2 = string.IsNullOrEmpty(str2) || ((str2.Length != 0x12) && (str2.Length != 15));
                    if (flag2)
                    {
                        Log.WriteAsync(string.Format("身份证号有误，身份证号:{0},长度:{1}", str2, str2.Length));
                    }
                    else
                    {
                        sender = new IdCardInfo
                        {
                            Fingerdata = builder.ToString(),
                            IdCardCode = str2,
                            IdCardName = unicode.GetString(bytes).Replace("\0", "").Trim(),
                            Address = unicode.GetString(buffer6).Replace("\0", "").Trim(),
                            Sex = unicode.GetString(buffer9).Replace("\0", "").Trim(),
                            Birthday = unicode.GetString(buffer5).Replace("\0", "").Trim()
                        };
                        sender.Birthday = this.GetTime(sender.Birthday, "yyyy-MM-dd");
                        sender.Department = unicode.GetString(buffer8).Replace("\0", "").Trim();
                        sender.Nation = unicode.GetString(buffer3).Replace("\0", "").Trim();
                        dateTime = this.GetTime(dateTime, "yyyy.MM.dd");
                        time = this.GetTime(time, "yyyy.MM.dd");
                        sender.IssueDate = dateTime;
                        sender.ExpiryDate = time;
                        if (!string.IsNullOrEmpty(dateTime) && !string.IsNullOrEmpty(time))
                        {
                            sender.Validate = dateTime + "-" + time;
                        }
                        else
                        {
                            Log.WriteAsync("有效期限出现乱码");
                            sender.Validate = "未知";
                        }
                        sender.Photo = CardZPPath;
                        Log.WriteAsync(string.Format("姓名:{0},性别:{1},出生日期{2},签发机关:{3},身份证号:{4},民族:{5},起始日期:{6},有效期限:{7}", 
                            new object[] { sender.IdCardName, sender.Sex, sender.Birthday, sender.Department, sender.IdCardCode, sender.Nation, dateTime, time }));
                    }
                    break;
                }
                return true;
            }
            catch (Exception exception)
            {
                sender = null;
                Log.WriteAsync("读身份证异常GetReadIDCard Error:" + exception.ToString());
                return false;
            }
            finally
            {
                isReading = false;
            }
        }
    

        private string GetTime(string dateTime, string format)
        {
            try
            {
                string s = dateTime;
                if (dateTime.Length == 8)
                {
                    string[] strArray = new string[] { dateTime.Substring(0, 4), "-", dateTime.Substring(4, 2), "-", dateTime.Substring(6, 2) };
                    s = string.Concat(strArray);
                }
                return DateTime.Parse(s).ToString(format);
            }
            catch (Exception)
            {
                return "";
            }
        }

        public bool InitCVRReader()
        {
            try
            {
                int num = 0;
                int port = 0;
                port = 0x3e9;
                while (true)
                {
                    bool flag2 = port <= 0x3f8;
                    if (flag2)
                    {
                        num = TermbDll_100D.CVR_InitComm(port);
                        if (num != 1)
                        {
                            port++;
                            continue;
                        }
                        Log.WriteAsync(string.Format("身份证阅读器初始化成功，USB口{0}", port));
                        return true;
                    }
                    else
                    {
                        port = 1;
                        while (true)
                        {
                            flag2 = port <= 0x10;
                            if (!flag2)
                            {
                                break;
                            }
                            num = TermbDll_100D.CVR_InitComm(port);
                            if (num != 1)
                            {
                                port++;
                                continue;
                            }
                            Log.WriteAsync(string.Format("打开身份证阅读器成功，串口{0}", port));
                            return true;
                        }
                    }
                    break;
                }
            }
            catch (Exception exception)
            {
                Log.WriteAsync("打开身份证阅读器异常，Error:" + exception.Message);
            }
            Log.WriteAsync("打开身份证阅读器失败");
            return false;
        }

        public bool InitCVRReader(int pPort)
        {
            CardZPPath = Path.Combine(AssemblyDirectory, "zp.BMP");
            CardWZFile = Path.Combine(AssemblyDirectory, "wz.txt");
            try
            {
                bool flag;
                Log.WriteAsync(string.Format("初始化身份证阅读器，串口参数{0}", pPort));
                int port = pPort;
                if (port <= 0)
                {
                    flag = this.InitCVRReader();
                }
                else if (TermbDll_100D.CVR_InitComm(port) == 1)
                {
                    Log.WriteAsync(string.Format("打开身份证阅读器成功，串口{0}", port));
                    flag = true;
                }
                else
                {
                    Log.WriteAsync("打开身份证阅读器失败");
                    flag = false;
                }
                return flag;
            }
            catch (Exception exception)
            {
                Log.WriteAsync("打开身份证阅读器异常，Error:" + exception.Message);
            }
            Log.WriteAsync("打开身份证阅读器失败");
            return false;
        }

        private void LoadConfig()
        {
            if (!File.Exists(_option.ConfigFilePath))
            {
                _option.Save();
            }
            _option.Load();
        }

        public override void Init(string inParam, out string outParam)
        {
            outParam = "";
            if (_bInited)
            {
                return;
            }
            if (InitCVRReader(_option.SerialPortNum))
            {
                _bInited = true;
                return;
            }
            if (InitCVRReader())
            {
                _bInited = true;
                return;
            }
            _error = string.Format("阅读器初始化失败。\n");
            Log.WriteAsync(_error);
        }
        /// <summary>
        /// 执行单次读取身份证操作
        /// </summary>
        /// <returns></returns>
        public bool Read(string inParams, out string outParams)
        {
            outParams = "";
            _error = "";
            if (!_bInited)
            {
                _error = "阅读器未初始化.";
                return false;
            }
            bool readSuccess = false;
            _error = "";
            try
            {
                IdCardInfo cardInfo = null;
                readSuccess = ReadCard(out cardInfo);
                if (readSuccess)
                {
                    outParams = GetCardInfoString(ref cardInfo);
                }

                return readSuccess;
            }
            catch (Exception ex)
            {
                _error = string.Format("读取身份证信息发生了异常.\n异常详情:{0}", ex.ToString());
                Log.WriteException(_error);
                return false;
            }
        }

        private string GetCardInfoString(ref IdCardInfo cardInfo)
        {
            JObject outParam = new JObject();
            outParam.Add("ZJHM", cardInfo.IdCardCode);
            outParam.Add("XM", cardInfo.IdCardName);
            outParam.Add("XB", cardInfo.Sex);
            outParam.Add("MZ", cardInfo.Nation);
            outParam.Add("DZ", cardInfo.Address);
            outParam.Add("CSRQ", cardInfo.Birthday);
            outParam.Add("QFDW", cardInfo.Department);
            outParam.Add("QFSJ", cardInfo.IssueDate);
            outParam.Add("SXSJ", cardInfo.ExpiryDate);
            outParam.Add("ZP", cardInfo.Photo);
            return outParam.ToString();
        }

        public override bool DoAction(string param, out string outParam)
        {
            return Read(param, out outParam);
        }

        public override void Start(string param, out string outParam)
        {
            outParam = null;
            poll = new Polling(Read, param);
            poll.TimeoutMilliSecond = TimeoutMillisecond;
            poll.ScanInterval = _option.ScanInterval;
            poll.Start(OnWorkingCompleted);
        }

        public override void Stop(string param, out string outParam)
        {
            outParam = null;
            if (poll != null)
            {
                poll.Stop();
                poll.Dispose();
                poll = null;
            }
        }

        public override void Exit(string inParams, out string outParam)
        {
            outParam = "";
            try
            {
                if (CloseCVRReader())
                {
                    _bExited = true;
                    _state = DeviceState.NotInitialized;
                    DeleteZPAndWZ();
                }
            }
            catch (Exception ex)
            {
                Log.WriteException(ex.ToString());
            }
            finally
            {
                _bInited = false;
            }
        }

        /// <summary>
        /// 清理身份证头像相片
        /// </summary>
        public void DeleteZPAndWZ()
        {
            try
            {
                if (File.Exists(CardZPPath))
                {
                    File.Delete(CardZPPath);
                }
                if (File.Exists(CardWZFile))
                {
                    File.Delete(CardWZFile);
                }
            }
            catch (Exception ex)
            {
                string strLog = string.Format("删除ZP发生了异常: {0}", ex.ToString());
                Log.WriteException(strLog);
            }
        }

        public override void ShowConfigDialog(string inParam)
        {
            FormSetting form = new FormSetting();
            form.ShowDialog();
        }
    }
}

